#include "SDKManager.h"
#include <QMessageBox>
#include <QMetaObject>
#include <QVariant>
#include <QDebug>
#include "CameraSDKInterface.h"
#include "ControlModuleSDKInterface.h"

/**
 * @brief SDK管理类构造函数
 * @param parent 父对象指针（用于内存管理）
 */
SDKManager::SDKManager(QObject *parent)
    : QObject(parent)
{
}
/**
 * @brief SDK管理类析构函数
 * 负责释放所有已加载的SDK实例资源
 */
SDKManager::~SDKManager()
{
    // 释放相机SDK资源
    for (auto iter = m_cameraSDKs.begin(); iter != m_cameraSDKs.end(); ++iter) {
        delete iter.value();
    }
    m_cameraSDKs.clear();
    
    // 释放控制模块SDK资源
    for (auto iter = m_controlModuleSDKs.begin(); iter != m_controlModuleSDKs.end(); ++iter) {
        delete iter.value();
    }
    m_controlModuleSDKs.clear();
}

/**
 * @brief 加载指定目录下的所有SDK插件
 * @param sdkDir SDK插件目录的绝对路径
 */
void SDKManager::loadSDKs(const QString &sdkDir) {
    QDir dir(sdkDir);
    if (!dir.exists()) {
        qWarning() << "SDK directory does not exist:" << sdkDir;
        return;
    }

    // Only consider typical plugin library files
    const QStringList nameFilters = {"*.dll", "*.so", "*.dylib"};
    const QStringList files = dir.entryList(nameFilters, QDir::Files);
    qDebug() << "Scanning SDK directory:" << sdkDir << "found" << files.size() << "candidate files";

    // Iterate over filtered files
    for (const QString &fileName : files) {
        const QString filePath = dir.filePath(fileName);
        qDebug() << "Trying to load SDK plugin:" << filePath;

        QPluginLoader loader(filePath);
        QObject *sdkObj = loader.instance();
        if (!sdkObj)
        {
            qWarning() << loader.errorString();
            continue;
        }

        qDebug() << "Plugin class:" << sdkObj->metaObject()->className();

        SDKInterface *base = qobject_cast<SDKInterface *>(sdkObj);
        if (!base)
        {
            qWarning() << "Not an SDKInterface-based plugin";
            loader.unload();
            continue;
        }
        connect(base,&SDKInterface::writeLog,this,&SDKManager::writeLog);
        if (base->deviceType() == SDKInterface::DeviceType::Camera)
        {
            auto cam = dynamic_cast<CameraSDKInterface *>(base);
            if (!cam)
            {
                qWarning() << "DeviceType=Camera but cast to CameraSDKInterface failed";
                loader.unload();
                continue;
            }
            m_cameraSDKs.insert(cam->sdkName(), cam);
            qDebug() << "Loaded camera SDK:" << cam->sdkName();
        }
        else
        {
            auto ctrl = dynamic_cast<ControlModuleSDKInterface *>(base);
            if (!ctrl)
            {
                qWarning() << "DeviceType=ControlModule but cast to ControlModuleSDKInterface failed";
                loader.unload();
                continue;
            }
            m_controlModuleSDKs.insert(ctrl->sdkName(), ctrl);
            qDebug() << "Loaded control module SDK:" << ctrl->sdkName();
        }
    }
}

/**
 * @brief 调用指定SDK的功能函数
 * @param sdkName 目标SDK名称（通过sdkName()获取）
 * @param funcName 目标函数名称（需为Q_INVOKABLE或槽函数）
 * @param args 参数列表（QVariant类型，最多支持10个参数）
 * @return 调用结果（QVariant类型，未找到SDK或调用失败返回无效QVariant）
 */
bool SDKManager::callSDKFunction(const QString& sdkName, const QString& funcName, const QVariantList& args, QVariant& result) {
    // 首先在相机SDK映射表中查找
    if (m_cameraSDKs.contains(sdkName)) {
        QObject* sdkObj = qobject_cast<QObject*>(m_cameraSDKs[sdkName]);
        if (!sdkObj) {
            result = QVariant();
            return false;
        } 
        QGenericArgument argList[10];
        int argCount = qMin(args.size(), 10);
        for (int i = 0; i < argCount; ++i) {
            argList[i] = Q_ARG(QVariant, args.at(i));
        }
        return QMetaObject::invokeMethod(
            sdkObj,
            funcName.toLatin1().constData(),
            Q_RETURN_ARG(QVariant, result),
            argCount > 0 ? argList[0] : QGenericArgument(),
            argCount > 1 ? argList[1] : QGenericArgument(),
            argCount > 2 ? argList[2] : QGenericArgument(),
            argCount > 3 ? argList[3] : QGenericArgument(),
            argCount > 4 ? argList[4] : QGenericArgument(),
            argCount > 5 ? argList[5] : QGenericArgument(),
            argCount > 6 ? argList[6] : QGenericArgument(),
            argCount > 7 ? argList[7] : QGenericArgument(),
            argCount > 8 ? argList[8] : QGenericArgument(),
            argCount > 9 ? argList[9] : QGenericArgument()
        );
    }
    
    // 然后在控制模块SDK映射表中查找
    if (m_controlModuleSDKs.contains(sdkName)) {
        QObject* sdkObj = qobject_cast<QObject*>(m_controlModuleSDKs[sdkName]);
        if (!sdkObj) {
            result = QVariant();
            return false;
        } 
        QGenericArgument argList[10];
        int argCount = qMin(args.size(), 10);
        for (int i = 0; i < argCount; ++i) {
            argList[i] = Q_ARG(QVariant, args.at(i));
        }
        return QMetaObject::invokeMethod(
            sdkObj,
            funcName.toLatin1().constData(),
            Q_RETURN_ARG(QVariant, result),
            argCount > 0 ? argList[0] : QGenericArgument(),
            argCount > 1 ? argList[1] : QGenericArgument(),
            argCount > 2 ? argList[2] : QGenericArgument(),
            argCount > 3 ? argList[3] : QGenericArgument(),
            argCount > 4 ? argList[4] : QGenericArgument(),
            argCount > 5 ? argList[5] : QGenericArgument(),
            argCount > 6 ? argList[6] : QGenericArgument(),
            argCount > 7 ? argList[7] : QGenericArgument(),
            argCount > 8 ? argList[8] : QGenericArgument(),
            argCount > 9 ? argList[9] : QGenericArgument()
        );
    }
    
    result = QVariant();
    return false;
}

/**
 * @brief 获取已加载的相机SDK列表
 * @return 相机SDK实例列表
 */
QList<CameraSDKInterface*> SDKManager::loadedCameraSDKs() const {
    return m_cameraSDKs.values();
}

/**
 * @brief 获取已加载的控制模块SDK列表
 * @return 控制模块SDK实例列表
 */
QList<ControlModuleSDKInterface*> SDKManager::loadedControlModuleSDKs() const {
    return m_controlModuleSDKs.values();
}

/**
 * @brief 根据SDK名称获取SDK实例
 * @param sdkName SDK名称
 * @return SDK实例指针，如果未找到则返回nullptr
 */
SDKInterface* SDKManager::getSDKByName(const QString& sdkName) const {
    // 首先在相机SDK映射表中查找
    if (m_cameraSDKs.contains(sdkName)) {
        return m_cameraSDKs[sdkName];
    }
    
    // 然后在控制模块SDK映射表中查找
    if (m_controlModuleSDKs.contains(sdkName)) {
        return m_controlModuleSDKs[sdkName];
    }
    
    return nullptr;
}

/**
 * @brief 根据SDK名称获取相机SDK实例
 * @param sdkName SDK名称
 * @return 相机SDK实例指针，如果未找到或类型不匹配则返回nullptr
 */
CameraSDKInterface* SDKManager::getCameraSDKByName(const QString& sdkName) const {
    return m_cameraSDKs.value(sdkName, nullptr);
}

/**
 * @brief 根据SDK名称获取控制模块SDK实例
 * @param sdkName SDK名称
 * @return 控制模块SDK实例指针，如果未找到或类型不匹配则返回nullptr
 */
ControlModuleSDKInterface* SDKManager::getControlModuleSDKByName(const QString& sdkName) const {
    return m_controlModuleSDKs.value(sdkName, nullptr);
}

/**
 * @brief 根据设备ID获取SDK名称
 * @param deviceId 设备ID
 * @return SDK名称，如果未找到则返回空字符串
 */
QString SDKManager::getSdkNameByDeviceId(const QVariant& deviceId) const {
    const QString key = deviceId.toString();
    if (m_deviceIdToSdkName.contains(key)) {
        return m_deviceIdToSdkName[key];
    }
    return QString();
}

/**
 * @brief 设置设备触发模式（简化版，仅传入设备ID）
 * @param deviceId 设备ID
 * @param mode 触发模式(0:自动, 1:手动, 2:外部触发等)
 * @return 操作结果，0表示成功，其他表示失败
 */
int SDKManager::setDeviceTriggerMode(const QVariant& deviceId, int mode) {
    QString sdkName = getSdkNameByDeviceId(deviceId);
    if (!sdkName.isEmpty()) {
        // 首先尝试从相机SDK中查找
        CameraSDKInterface* cameraSDK = getCameraSDKByName(sdkName);
        if (cameraSDK) {
            return cameraSDK->setDeviceTriggerMode(deviceId, mode) ? 1 : -1;
        }
        
        // 然后尝试从控制模块SDK中查找
        ControlModuleSDKInterface* controlSDK = getControlModuleSDKByName(sdkName);
        if (controlSDK) {
            return controlSDK->setDeviceTriggerMode(deviceId, mode) ? 1 : -1;
        }
    }
    return -1;
}

/**
 * @brief 检索所有可用的相机设备
 * 在检索过程中会自动建立设备ID和SDK名称的关联
 * @return 设备ID列表，如果没有找到设备则返回空列表
 */
QList<QVariant> SDKManager::discoverCameraDevices() {
    QList<QVariant> allDevices;
    
    // 遍历所有加载的相机SDK
    QList<CameraSDKInterface*> cameraSDKs = loadedCameraSDKs();
    for (CameraSDKInterface* sdk : qAsConst(cameraSDKs)) {
        if (sdk) {
            QList<QVariant> devices;
            // 调用SDK的searchDevices方法搜索设备
            if (sdk->searchDevices(devices)) {
                // 遍历搜索到的设备，建立设备ID和SDK名称的关联
                for (const QVariant& deviceId : devices) {
                    // 注册设备ID和SDK名称的关联
                    m_deviceIdToSdkName.insert(deviceId.toString(), sdk->sdkName());
                    // 将设备ID添加到总列表中
                    allDevices.append(deviceId);
                }
            }
        }
    }
    
    return allDevices;
}

/**
 * @brief 检索所有可用的控制模块设备
 * 在检索过程中会自动建立设备ID和SDK名称的关联
 * @return 设备ID列表，如果没有找到设备则返回空列表
 */
QList<QVariant> SDKManager::discoverControlModuleDevices() {
    QList<QVariant> allDevices;
    
    // 遍历所有加载的控制模块SDK
    QList<ControlModuleSDKInterface*> controlSDKs = loadedControlModuleSDKs();
    for (ControlModuleSDKInterface* sdk : controlSDKs) {
        if (sdk) {
            QList<QVariant> devices;
            // 调用SDK的searchDevices方法搜索设备
            if (sdk->searchDevices(devices)) {
                // 遍历搜索到的设备，建立设备ID和SDK名称的关联
                for (const QVariant& deviceId : devices) {
                    // 注册设备ID和SDK名称的关联
                    m_deviceIdToSdkName.insert(deviceId.toString(), sdk->sdkName());
                    // 将设备ID添加到总列表中
                    allDevices.append(deviceId);
                }
            }
        }
    }
    
    return allDevices;
}

bool SDKManager::connectDevice(const QVariant& deviceId) {
    QString sdkName = getSdkNameByDeviceId(deviceId);
    if (sdkName.isEmpty()) return false;

    // 优先尝试相机SDK
    if (CameraSDKInterface* cameraSDK = getCameraSDKByName(sdkName))
    {
        if(!cameraSDK->openDevice(deviceId))
        {
            return false;
        }
        emit cameraConnected(deviceId.toString());
        return true;
    }
    // 再尝试控制模块SDK
    if (ControlModuleSDKInterface* ctrlSDK = getControlModuleSDKByName(sdkName))
    {
        if(!ctrlSDK->openDevice(deviceId))
        {
            return false;
        }
        emit controlModuleConnected(deviceId.toString());
        return true;
    }
    return false;
}

void SDKManager::disconnectDevice(const QVariant& deviceId) {
    QString sdkName = getSdkNameByDeviceId(deviceId);
    if (sdkName.isEmpty()) return;

    // 优先尝试相机SDK
    if (CameraSDKInterface* cameraSDK = getCameraSDKByName(sdkName)) {
//        unsetImageCaptureCallback(deviceId);
        cameraSDK->closeDevice(deviceId);
        emit cameraDisconnected(deviceId.toString());
        return;
    }
    // 再尝试控制模块SDK
    if (ControlModuleSDKInterface* ctrlSDK = getControlModuleSDKByName(sdkName)) {
        ctrlSDK->closeDevice(deviceId);
        emit controlModuleDisconnected(deviceId.toString());
        return;
    }
}

QSize SDKManager::getDevicePixelSize(const QVariant& deviceId) {
    QString sdkName = getSdkNameByDeviceId(deviceId);
    if (sdkName.isEmpty()) return QSize();
    if (CameraSDKInterface* cameraSDK = getCameraSDKByName(sdkName)) {
        return cameraSDK->getDevicePixelSize(deviceId);
    }
    return QSize();
}

bool SDKManager::setImageCaptureCallback(const QVariant& deviceId, ImageCallback callback) {
    QString sdkName = getSdkNameByDeviceId(deviceId);
    if (sdkName.isEmpty()||callback==nullptr) return false;
    if (CameraSDKInterface* cameraSDK = getCameraSDKByName(sdkName)) {
        cameraSDK->setImageCaptureCallback(deviceId, callback);
        return true;
    }
    return false;
}

void SDKManager::unsetImageCaptureCallback(const QVariant& deviceId) {
    QString sdkName = getSdkNameByDeviceId(deviceId);
    if (sdkName.isEmpty()) return;
    if (CameraSDKInterface* cameraSDK = getCameraSDKByName(sdkName)) {
        cameraSDK->unsetImageCaptureCallback(deviceId);
    }
}

QVariant SDKManager::getControlModuleParameter(const QVariant& deviceId, const QString& paramName) const {
    QString sdkName = getSdkNameByDeviceId(deviceId);
    if (sdkName.isEmpty()) return QVariant();
    QVariant result;
    QVariantList args{deviceId, QVariant(paramName)};
    // 控制模块接口的getModuleParameter统一返回QVariant
    const_cast<SDKManager*>(this)->callSDKFunction(sdkName, "getModuleParameter", args, result);
    return result;
}

/**
 * @brief 获取设备参数对话框
 * @param deviceId 设备ID
 * @return 参数对话框指针，如果不支持则返回nullptr
 */
QDialog* SDKManager::getDeviceParameterDialog(const QVariant& deviceId,QWidget* parent) {
    QString sdkName = getSdkNameByDeviceId(deviceId);
    if (sdkName.isEmpty()) return nullptr;
    
    // 优先尝试相机SDK
    if (CameraSDKInterface* cameraSDK = getCameraSDKByName(sdkName)) {
        return cameraSDK->getParametersDialog(deviceId,parent);
    }
    
    // 再尝试控制模块SDK
    if (ControlModuleSDKInterface* ctrlSDK = getControlModuleSDKByName(sdkName)) {
        return ctrlSDK->getParametersDialog(deviceId,parent);
    }
    
    return nullptr;
}

/**
 * @brief 获取设备快捷参数设置widget
 * @param deviceId 设备ID
 * @return 快捷参数设置widget指针，如果不支持则返回nullptr
 */
QWidget* SDKManager::getDeviceQuickParameterWidget(const QVariant& deviceId) {
    QString sdkName = getSdkNameByDeviceId(deviceId);
    if (sdkName.isEmpty()) return nullptr;
    
    // 优先尝试相机SDK
    if (CameraSDKInterface* cameraSDK = getCameraSDKByName(sdkName)) {
        return cameraSDK->getQuickParametersWidget(deviceId);
    }
    
    // 再尝试控制模块SDK
    if (ControlModuleSDKInterface* ctrlSDK = getControlModuleSDKByName(sdkName)) {
        return ctrlSDK->getQuickParametersWidget(deviceId);
    }
    
    return nullptr;
}

/**
 * @brief 设置设备参数
 * @param deviceId 设备ID
 * @param params 设备参数映射，使用QVariantMap作为万能变量类型
 * @return 设置成功返回true，失败返回false
 */
bool SDKManager::setDeviceParameters(const QVariant& deviceId, const QVariantMap& params) {
    QString sdkName = getSdkNameByDeviceId(deviceId);
    if (sdkName.isEmpty()) {
        return false;
    }

    SDKInterface* pSDK = getSDKByName(sdkName);
    if (!pSDK) {
        return false;
    }

    return pSDK->setDeviceParameters(deviceId, params);
}

/**
 * @brief 获取设备参数
 * @param deviceId 设备ID
 * @param configName 配置名称输出
 * @param params 设备参数映射输出，使用QVariantMap作为万能变量类型
 * @return 获取成功返回true，失败返回false
 */
bool SDKManager::getDeviceParameters(const QVariant &deviceId, QString &configName, QVariantMap &params)
{
    QString sdkName = getSdkNameByDeviceId(deviceId);
    if (sdkName.isEmpty()) {
        return false;
    }

    SDKInterface* pSDK = getSDKByName(sdkName);
    if (!pSDK) {
        return false;
    }

    return pSDK->getDeviceParameters(deviceId, configName, params);
}

/**
 * @brief 设置预设参数
 * @param params 预设参数映射，使用QVariantMap作为万能变量类型
 * @return 设置成功返回true，失败返回false
 */
bool SDKManager::setPresetParameters(const QString& configName ,const QVariantMap& params) {
    QString moduleConfigName;
    QVariantMap oldParams;
    // 遍历所有相机SDK
    for (auto it = m_cameraSDKs.begin(); it != m_cameraSDKs.end(); ++it)
    {
        if(it.value()->getPresetParameters(moduleConfigName,oldParams)&&moduleConfigName==configName)
        {
            return it.value()->setPresetParameters(params);
        }
    }
    
    // 遍历所有控制模块SDK
    for (auto it = m_controlModuleSDKs.begin(); it != m_controlModuleSDKs.end(); ++it)
    {
        if(it.value()->getPresetParameters(moduleConfigName,oldParams)&&moduleConfigName==configName)
        {
            return it.value()->setPresetParameters(params);
        }
    }
    
    return false;
}

/**
 * @brief 获取预设参数
 * @param configName 配置名称输出
 * @param params 预设参数映射输出，使用QVariantMap作为万能变量类型
 * @return 获取成功返回true，失败返回false
 */
bool SDKManager::getPresetParameters(const QString& configName, QVariantMap& params) {
    QString moduleConfigName;
    QVariantMap moduleParams;
    // 遍历所有相机SDK
    for (auto it = m_cameraSDKs.begin(); it != m_cameraSDKs.end(); ++it)
    {
        if(it.value()->getPresetParameters(moduleConfigName,moduleParams)&&moduleConfigName==configName)
        {
            params=moduleParams;
            return true;
        }
    }

    // 遍历所有控制模块SDK
    for (auto it = m_controlModuleSDKs.begin(); it != m_controlModuleSDKs.end(); ++it)
    {
        if(it.value()->getPresetParameters(moduleConfigName,moduleParams)&&moduleConfigName==configName)
        {
            params=moduleParams;
            return true;
        }
    }

    return false;
}
